Сравнение языков программирования

Материал из Википедии — свободной энциклопедии

Перейти к: навигация, поиск
 Условные обозначения 
+ Указанная возможность присутствует
- Указанная возможность отсутствует
+/- Возможность поддерживается не полностью
-/+ Возможность поддерживается очень ограниченно
 ? Нет данных
x Постановка вопроса не применима к языку

В приведенной ниже таблице отмечено наличие или отсутствие тех или иных возможностей в некоторых популярных сегодня языках программирования. Столбцы упорядочены по алфавиту. Если возможность в языке недоступна напрямую, но может быть эмулирована с помощью других средств, то в таблице отмечено, что её нет.

При заполнении таблицы учтены только фактические данные, при том, что наличие возможности не обязательно является преимуществом языка, а отсутствие — недостатком.




[править] Парадигмы

Возможность\Язык Ada C C++ C# D Eiffel Erlang F# Groovy Java JavaScript Haskell Common Lisp Nemerle Perl PHP Python Ruby Scala Smalltalk Tcl VB.NET Delphi OCaml
Императивный + + + + + + - + + + + +
[1]
+ + + + + + + + + + + +
Объектно-ориентированный + - + + + + -
[2]
+ + + +
[3]
-
[4]
+ + + + + + + + + + + +
Функциональный - - -/+ +/- +/- +/- + + + - + + + + + +/- +/- + + + + +/- -/+ +
Рефлексивный - - - -/+ -  ? + -/+ -/+ -/+ + - + -/+ +/- + + + -/+ + + -/+ -/+ -
Обобщенное программирование + - + + + +/- + + + + + + + + + + + + + + - + + +
Логический - - - - - - - - - - - +/-
[5]
+/-
[6]
+/- - - - -  ? +/- - - - -
Декларативный - - - +/- -/+  ? + + + - - + + [7] + -/+
[8]
+ + + + +/- - +/- - +
Распределенный +
[9]
+/-
[10]
+/-
[10]
-/+
[11]
- + + - -/+ - - +
[12]
+/- - - - -/+ -/+  ? +/-  ? - - -
Ada C C++ C# D Eiffel Erlang F# Groovy Java JavaScript Haskell Common Lisp Nemerle Perl PHP Python Ruby Scala Smalltalk Tcl VB.NET Delphi OCaml

[править] Типизация

Возможность\Язык Ada  C  C++ C#  D  Eiffel Erlang F# Groovy Java JavaScript Haskell Common Lisp Nemerle Perl пэхэпэ!11 Python Ruby Scala Smalltalk Tcl VB.NET Delphi OCaml
Статическая типизация + + + + + + - + + + - + +/- [13] + +/-
[14]
- - - + +/-
[15]
- + + +
Динамическая типизация - - - +
[16]
- - + -/+ [17] + - + +
[18]
+ - + + + + - + + +
[19]
+
[20]
-
Явная типизация + + + + + + -/+
[21]
+ + + - + +/- [13] + -/+
[22]
+/- +/-
[23]
- + +/-
[24]
- + + +
Неявная типизация - - -/+ +/- + - + + + - + + + + + + + + + + + + - +
Неявное приведение типов без потери данных -/+
[25]
+ + + + + - - + + + - + + + + + +  ? + + + + -
Неявное приведение типов с потерей данных - + + - + - - - - -  ? - -  ? +
[26]
+ - -  ? + + + + -
Неявное приведение типов в неоднозначных ситуациях - + + + + - - - - - + - - + +
[27]
+ - -  ? - + + - -
Алиасы типов + + + + + - x + - - x + + [28] + x x x x  ?  ? x - + +
Вывод типов переменных из инициализатора - - - + + - x + - - x + +/-
[29]
+ x x x x +  ? x + - +
Вывод типов переменных из использования - - - - - - x + - - x + +/-
[29]
+ x x x x  ?  ? x  ? - +
Вывод типов-аргументов при вызове метода - - + + + + x + + + x + +/-
[29]
+ x x x x +  ? x + - +
Вывод сигнатуры для локальных функций - - - -  ? - x + - - x + +/- [29] + x  ? x x -  ? x  ? - +
Параметрический полиморфизм - x - + + + x + + + - + + + x + x x +  ? x + - +
Параметрический полиморфизм с ковариантностью - x - +/-
[30]
 ? + x + - - - x + +/-  ?  ? x x +  ? x - -  ?
Параметрический полиморфизм высших порядков - x - - -  ? x - - - - + + - x  ? x x +  ? x - -  ?
Информация о типах в runtime -/+
[31]
- -/+
[32]
+ + + + + + + + - + + + + + + + + + + + -
Информация о типах-параметрах в runtime - - -/+ +  ?  ? - + - - + - + +  ? + +  ? -  ? - + + -
Ada C C++ C# D Eiffel Erlang F# Groovy Java JavaScript Haskell Common Lisp Nemerle Perl PHP Python Ruby Scala Smalltalk Tcl VB.NET Delphi OCaml

[править] Компилятор/интерпретатор

Возможность\Язык Ada C C++ C#  D  Eiffel Erlang F# Groovy Java JavaScript Haskell Common Lisp Nemerle Perl PHP Python Ruby Scala Smalltalk Tcl VB.NET Delphi Ocaml
Open-source компилятор (интерпретатор) + + + + + + + + + + + + + + + + + + + +
[33]
+ + +
[34]
+
Возможность компиляции + + + + + + -/+
[35]
+ + + + + + + + +
[36]
+ + + +
[37]
- + + +
Bootstrapping компилятор + + + + -  ? + + + +
[38]
+
[39]
+ + [40] +  ? x +
[41]
+ + +
[42]
x  ? + +
Многопоточная компиляция + + + - +  ? + + + +  ? + + -  ?  ? x x - - x  ?  ? +
Интерпретатор командной строки +/-
[43]
-/+
[44]
+/-
[44]
-
[45]
-  ? + + + - +
[46]
+ + + + + + + + +
[47]
+ - - +
Условная компиляция +/-
[48]
+ + + +  ? + +  ? -/+
[49]
-/+
[50]
+ + [51] + + + x x  ? + x + + x
Ada C C++ C# D Eiffel Erlang F# Groovy Java JavaScript Haskell Common Lisp Nemerle Perl PHP Python Ruby Scala Smalltalk Tcl VB.NET Delphi OCaml

[править] Управление памятью

Язык Ada  C  C++ C#  D  Eiffel Erlang F# Groovy Java JavaScript Haskell Common Lisp Nemerle Perl PHP Python Ruby Scala Smalltalk Tcl VB.NET Delphi OCaml
Создание объектов на стеке + + + + + -/+
[52]
 ?  ? + +  ? +/-
[53]
+/-
[54]
+ - - - -  ?  ? - - -/+
[55]
 ?
Неуправляемые указатели + + + + + - - - - - [56] - - [56] - [56] - - - -
[57]
- - +
[58]
- - + -
Ручное управление памятью + + + +[59] + - - - - - [56] - - [56] - [56] - - - - [56] - - +
[60]
- - + -
Сборка мусора -/+
[61]
-
[62]
-
[62]
+ + + + + + + + + + + + + + + + + + + -
[63]
+

[править] Управление потоком вычислений

Язык Ada  C  C++ C#  D  Eiffel Erlang F# Groovy Java JavaScript Haskell Common Lisp Nemerle Perl PHP Python Ruby Scala Smalltalk Tcl VB.NET Delphi OCaml
Инструкция goto + + + + + - - x - -
[64]
- x + [65] - + + - -/+
[66]
- -/+
[67]
- + + -
Инструкции break без метки + + + + + - - x + + + x + [68] + + + + + -  ? + + + +/-
[69]
Инструкция break с меткой + - - - + - - x + + + x + [70] + + + - + -  ? - + - x
Поддержка try/catch + - + + + +
[71]
+ + + + + + +
[72]
+ +
[73]
+ + + + + + + + +
Блок finally -/+
[74]
- - + + - - + + + +
[75]
+ +
[76]
+ - - + + + + + + + -
[77]
Блок else (исключения) - - - + - - + - + +
[78]
 ? + +
[72]
- +
[79]
- + + -  ? + + + +
Перезапуски  ? -  ? -  ?  ?
- -  ?  ?  ?  ? +
- -
[80]
 ?  ?  ?  ?  ? - -  ?  ?
Ленивые вычисления  ? - - -/+
[81]
- -
- +/- [82] - - - + -
[83]
 ? -
- + -  ? - - -/+
[84]
- + [85]
Continuations  ?  ?  ? -  ?  ?
- -  ?  ?  ? + - [86]
-  ?
 ? + +  ? + + -  ? +/-
[87]
Легковесные процессы (Сoroutines) - - - - - + + -  ? +/-
[88]
- + +/-[89] - +
[90]
 ? +/-
[91]
 ?  ? + + - - +/- [92]

[править] Типы и структуры данных

Язык Ada  C  C++ C#  D  Eiffel Erlang F# Groovy Java JavaScript Haskell Common Lisp Nemerle Perl PHP Python Ruby Scala Smalltalk VB.NET Delphi OCaml
Кортежи - - +/-
[93]
+/-
[94]
+/- + + + + - - + + + + - + + + + +/-
[94]
- +
Алгебраические типы данных -/+
[95]
- - -  ?  ? x
[96]
+  ? - x
[96]
+ x
[96]
 ? x
[96]
x
[96]
x
[96]
x
[96]
 ? x
[96]
- -/+
[95]
+
Многомерные массивы  ? +/- +/- +  ?  ? - + + +/- +/- x
[97]
+ + +/- +/- + +  ?  ? + + +
Динамические массивы  ? - [98] + + +  ? - + +  ? + x
[97]
+ + + + + +  ?  ? + + +
Ассоциативные массивы  ? - + + +  ? - + +  ? + x
[97]
+ + + + + +  ?  ? + +/- +
Контроль границ массивов  ? - -/+
[99]
+ + + x
[97]
+  ? + x
[100]
x
[97]
+ + x
[100]
x
[100]
+  ?  ?  ? + + +
[101]
Цикл foreach +/-
[102]
- +/-
[103]
+ + - +/-
[104]
+ + + +
[105]
+ +
[106]
+ + + + + + + + + +
List comprehensions - - - -/+
[107]
- - + + - - - + + +  ? - +  ? + + + - +/-
Целые числа произвольной длины - - - +
[108]
-  ? + + + +
[109]
 ? + + +
[108]
+  ? + + +
[110]
+ +
[108]
- +
[111]
Целые числа с контролем границ + - - - -  ? - - - - - - + [112] - -
[113]
- -  ? -  ? - + -

[править] Объектно-ориентированные возможности

Язык Ada  C  C++ C#  D  Eiffel Erlang F# Groovy Java JavaScript Haskell Common Lisp Nemerle Perl PHP Python Ruby Scala Smalltalk VB.NET Delphi OCaml
Интерфейсы  ? - +/- + +  ? x +  ? +  ? x x [114] + +/- [115] + +  ?  ?  ? + + +
Мультиметоды - - - - - - x - + -
[116]
- x
+ - -
[116]
- -
[116]
-
[116]
- - - - -
Mixins  ? - - - +  ? x  ?  ? -
 ? x
+  ?  ?
 ?  ?
+
+ +  ? + [117]  ?
Переименование членов при наследовании  ? x - -  ? + x - - -  ? x - - -/+ - -  ?  ? - - -  ?
Множественное наследование  ? x + - - + x - - -  ? x + - + - +  ?  ? - - - +
Решение конфликта имен при множественном наследовании  ? x -/+
[118]
x x +
[119]
x x  ? x  ? x +[120] x + x +  ?  ? x x x  ?

[править] Функциональные возможности

Язык Ada  C  C++ C#  D  Eiffel Erlang F# Groovy Java JavaScript Haskell Common Lisp Nemerle Perl PHP Python Ruby Scala Smalltalk VB.NET Delphi OCaml
Декларации чистоты функций - - - - + [121] - - - - - - + - - - - - - - - - - -
First class functions  ? -/+ [122] -/+ [123] + +  ? + + + - +
+ + +
+  ?
+
+ + +  ? +
[124]
+
Анонимные функции  ? - - + [125] +  ? + + + - +
+ + [126] +
+ +
+/-
+ + +  ? +
[124]
+
Лексические замыкания - - - + + + + + + - + + + + +  ? + + + + + +
[124]
+
Каррирование - - - - - - - + - - -
+ - -
- -
-
- + - - - +

[править] Разное

Возможность\Язык Ada C C++ C# D Eiffel Erlang F# Groovy Java JavaScript Haskell Common Lisp Nemerle Perl PHP Python Ruby Scala Smalltalk VB.NET Delphi Ocaml
Макросы -/+ -/+
[127]
-/+
[128]
- -/+
[129]
- -/+ - - - - +/-
[130]
+ +
-  ? - +/- - - - - -/+
[131]
Шаблоны/Generics + - + + + + x
[132]
+ + + x
[132]
-
[133]
x
[132]
+ x
[132]
- x
[132]
x
[132]
+ x
[132]
+ +
[134]
+/-
Поддержка Unicode в идентификаторах + -/+
[135]
-/+
[136]
+ +  ? - + + + + + + [137] + +/- -/+ +
[138]
+
[139]
+ + + + +
Перегрузка функций + - + + + - + + + + -/+
[140]
+ + [141] + -
[142]
- -
[143]
- +  ? + + +
Динамические переменные  ? - -  ?  ?  ?
-  ?  ?  ?  ?  ? + [144]
 ? +
- -  ?  ?  ?  ?  ?  ?
Именованные параметры + - - +
[145]
- - - +/- + - -/+
[146]
- + [147] + + - + +  ? -/+
[148]
+ -/+
[149]
+
Значения параметров по умолчанию + - + +
[145]
+ - +/-
[150]
- + - - - + [151] + +/-
[152]
+ + + + +/- + + +
Локальные функции + -/+
[153]
-/+
[154]
+/- + - + + - +/-
[155]
+ + + [156] + +/- + + + + - +/- + +
Сопоставление с образцом - - - +/- - - + + - - - + +/- [157] + +  ? -
[143]
- +  ? - - +
Контрактное программирование - - - +
[158]
+ +  ? +/-
[158]
+/- +/-
[159]
 ? +
[160]
+ +  ?  ? +/- +/-  ?  ? +
[158]
- -

[править] Стандартизация

Язык Ada  C  C++ C#  D  Eiffel Erlang F# Groovy Java JavaScript Haskell Common Lisp Nemerle Perl PHP Python Ruby Scala Smalltalk VB.NET Delphi OCaml
 Стандарты  ISO ANSI ГОСТ ISO ANSI ISO ISO ECMA - ISO ECMA - - - - ECMA - ANSI - - - - - - ANSI - - -

[править] Примечания

  1. Императивный/Haskell. Монады позволяют выполнять императивные действия.
  2. ООП/Erlang. Можно провести параллель между процессами в Эрланге и объектами в определении Алана Кея [1].
  3. ООП/Javascript. Прототипная модель ООП.
  4. ООП/Haskell. Классы типов и семейства типов перекрывают возможности ООП.
  5. Логический/Haskell. Изначально инструментов для логического программирования не встроено, но есть сторонние библиотеки. Существует академический функционально-логический язык Curry, берущий Haskell за основу.
  6. Логический/Common Lisp. Логическая парадигма изначально в язык не встроена, но реализуется средствами языка.
  7. В языке существует множество декларативных конструкций, и, более того, возможность создавать свои, с помощью макросов.
  8. Декларативный/Perl. Только регулярные выражения.
  9. Распределённый/Ada. См. Annex E. Distributed Systems.
  10. 1 2 Распределённый/C и C++. Многие распространённые компиляторы поддерживают директивы для распараллеливания в рамках технологий MPI и OpenMP.
  11. Распределённый/C#. Существуют проекты распределённых модификаций языка, например Parallel C#.
  12. Распределённый/Haskell. Модель языка подразумевает распределённое использование, при этом не требуя от программиста усилий на реализацию распределённости. Один из поддерживающих эту возможность компиляторов - Glasgow Distributed Haskell.
  13. 1 2 ANSI стандарт языка предусматривает опциональные декларации типов, которые какие-либо конкретные реализации могут использовать по своему усмотрению. Большинство современных реализаций CL принимают декларации типов в расчет, и используют для статической проверки типов и в целях оптимизации.
  14. Статическая типизация/Perl. С версии 5.6. Только для не встроенных типов.
  15. Статическая типизация/Smalltalk. Возможность статической типизации есть в диалекте Smalltalk - Strongtalk'е.
  16. Динамическая типизация/C#. Посредством специального псевдо-типа dynamic с версии 4.0.
  17. Динамическая типизация/F#. Компилятор поддерживает синтаксический сахар в виде преобразования использования оператора (?) xml?name в вызов xml.op_Dynamic("name"), на базе чего может быть реализована имитация динамической типизации.
  18. Динамическая типизация/Haskell. Обеспечивается модулем Data.Dynamic.
  19. Динамическая типизация/VB.NET. Контролируемо с помощью Option Strict.
  20. Динамическая типизация/Delphi. Посредством специального типа Variant.
  21. Явная типизация/Erlang. Можно использовать т.н. type test BIFs. См. [2]
  22. Явная типизация/Perl. См. Prototypes в man perlsub.
  23. Явная типизация/Python. Частично в Python 3.0.
  24. Явная типизация/Smalltalk. Есть в Strongtalk.
  25. Неявное приведение типов/Ada. См. 4.6 Type Conversions.
  26. Неявное приведение с потерей данных/Perl. При сложении строки с числом: $a = '5aa'; print $a + 0; Напечатает: 5
  27. Неявное приведение в неоднозначных ситуациях/Perl. Не совсем корректно, т.к. в Perl эти ситуации однозначны: 1 + "2" # 3  и  1 . "2" # "12"
  28. Макрос DEFTYPE
  29. 1 2 3 4 Вывод типов/Common Lisp. Некоторые компиляторы Common Lisp, такие как SBCL, поддерживают частичный вывод типов.
  30. Параметрический полиморфизм с ковариантностью/C#. Доступно начиная с C# 4.0 для типов интерфейсов и делегатов.
  31. Информация о типах в runtime/Ada. Точный тип узнать можно (Ada.Tags), но полной поддержки отражения в языке нет. Можно узнать имя, предков, интерфейсы, сериализовать объект, но нельзя запросить список методов.
  32. Информация о типах в runtime/С++. Можно сравнить типы на точное совпадение, узнать имя типа (typeid), приводить типы вниз по иерархии наследования.
  33. Open-source компилятор (интерпретатор)/Smalltalk. В любом диалекте Smalltalk исходники всего, кроме виртуальной машины, (т.е. библиотека классов, компилятор в байткод, среда разработки, сторонние библиотеки и пр.) принципиально открыты - это свойство языка. Из основных диалектов исходники виртуальной машины открыты у GNU Smalltalk, Squeak и Strongtalk.
  34. Open-source компилятор (интерпретатор)/Delphi. FreePascal и Lazarus.
  35. Возможность компиляции/Erlang. HiPE - High Performance Erlang. Доступен только для *nix-систем.
  36. Существуют PHP-компиляторы, вполне корректно комилирующие любые PHP-скрипты. Например, Roadsend PHP Compiler.
  37. Возможность компиляции/Smalltalk. Стандартная реализация в Smalltalk - это прозрачная компиляция в байт-код (в момент сохранения изменённого исходного кода) с последующим исполнением на виртуальной машине, часто с использованием JIT-компилятора. Однако некоторые диалекты поддерживают прямую компиляцию в машинные коды. В часности, к таким диалектам относятся Smalltalk MT и Smalltalk/X.
  38. Bootstrapping компилятор/Java. Java Compiler API появилось в версии 6.0.
  39. Narcissus.
  40. Например, SBCL
  41. Bootstrapping компилятор/Python. Проект PyPy.
  42. Bootstrapping компилятор/Smalltalk. Компилятор в байт-коды изначально написан на самом Smalltalk и исполняется внутри виртуальной машины. Кроме этого также есть примеры виртуальных машин Smalltalk, написанных на самом Smalltalk - к ним, в частности, относится виртуальная машина Squeak, написанная на подмножестве Smalltalk, которое потом транслируется в C и компилируется в машинные коды. При этом собственно разработка и отладка виртуальной машины Squeak осуществляется внутри работающей системы Squeak.
  43. Интерпретатор командной строки/Ada. Business Shell (BUSH).
  44. 1 2 Интерпретатор командной строки/C++. C++ интерпретатор CINT.
  45. Планируется к версии 5.0 языка.
  46. Rhino Shell.
  47. В диалекте GNU Smalltalk реализована поддержка командной строки.
  48. Условная компиляция/Ada. Поскольку использование препроцессора существенно осложняет работу утилит, отличных от компилятора, работающих с исходными текстами, в стандарт эта возможность не входит. Здесь: Conditional Compilation описывается, как можно организовать условно компилируемый код. В качестве резервного варианта предоставляется препроцессор gnatprep.
  49. Условная компиляция/Java. Утверждения (операторы assert) всегда включаются компилятором в байт-код и могут быть разрешены (по умолчанию запрещены, то есть игнорируются) при запуске виртуальной машины ключом -ea/-enableassertion.
  50. [3].
  51. Макросы лиспа позволяют при компиляции вычислять произвольные выражения, включая, естественно, конструкции ветвлений.
  52. Компилятор должен решать, какие классы будут представлены "простыми" типами и будут, в том числе, размещаться в стеке.
  53. Создание объектов на стеке/Haskell. В GHC при помощи Unboxed Types / Unboxed Arrays.
  54. Стандарт языка предусматривает декларацию DYNAMIC-EXTENT, которая может трактоваться компилятором как указание выделить место под объект на стеке.
  55. Создание объектов на стеке/Delphi. В Delphi имеется 2 объектных модели - старая (унаследована из Turbo Pascal) и новая. Создание объектов на стеке возможно только в старой объектной модели.
  56. 1 2 3 4 5 6 7 Через FFI (foreign function interface)
  57. Можно с помощью модуля стандартной библиотеки - ctypes.
  58. Неуправляемые указатели/Smalltalk. В Smalltalk есть возможность низкоуровневой работы с памятью, но только в адресном пространстве, предоставляемом виртуальной машиной.
  59. unsafe + System.Runtime.InteropServices
  60. Ручное управление памятью/Smalltalk. При низкоуровневой работе в пространстве памяти, предоставляемом виртуальной машиной, можно вручную создавать и удалять объекты, записывая данные в соответствующие адреса памяти. Аналогично можно вручную управлять размещением объектов в памяти.
  61. Сборка мусора/Ada. Только на некоторых платформах (.NET и JVM) или при помощи библиотек (AdaCL:GC). Тем не менее, практически все программы на Ada могут работать как с ним, так и без него. В этом смысле к сборке мусора применительно к Аде следует относиться не как к инженерному решению, а как к оптимизации управления памятью.
  62. 1 2 Сборка мусора/C и C++. В стандарте языка и в стандартных библиотеках нет сборки мусора. Однако существуют сборщики мусора для C и C++ в виде библиотек. Например, BoehmGC (англоязычный раздел).
  63. Сборка мусора/Delphi. Если не считать Delphi.NET.
  64. Инструкция goto/Java. Является зарезервированным словом.
  65. Специальный оператор GO. Все конструкции циклов в CL, фактически, являются макросами-надстройками над этой инструкцией.
  66. Инструкция goto/Ruby. В языке goto нет, но есть библиотека реализующая его.
  67. Инструкция goto/Smalltalk. В стандарте языка goto нет, но существуют библиотеки, реализующие функционал goto через управление стеком исполнения. Используются крайне редко, это скорее proof of concept(англ.).
  68. Макрос RETURN. Фактически, является частным случаем RETURN-FROM.
  69. заменяется исключениями, также реализуется с помощью Camlp4 http://code.google.com/p/ocaml-break-continue/
  70. Специальный оператор RETURN-FROM
  71. Можно либо повторить выполнение метода, либо пробросить исключение далее
  72. 1 2 Java-style try-catch блок реализуется макросом handler-case. Кроме того, в возможности системы обработки исключений Common Lisp входит система т.н. перезапусков(restarts), которые позволяют обрабатывать исключения "изнутри" без раскрутки стека вызовов функций
  73. При помощи оператора eval
  74. Блок finally/Ada. В стандарте языка finally нет, но существуют библиотеки, реализующие функционал finally. Используются крайне редко, это скорее proof of concept(англ.).
  75. [4]
  76. Специальный оператор UNWIND-PROTECT
  77. реализуется на camlp4 http://bluestorm.info/camlp4/dev/try/pa_tryfinally.ml.html
  78. При помощи нескольких последовательных catch
  79. При помощи eval or {...}
  80. Частично реализуются нестандартным модулем Runops::Resume
  81. Конструкции yield return, запросы LINQ, в FCL 4.0 войдёт тип Lazy.
  82. Seq-генераторы, модуль Lazy стандартной библиотеки F#.
  83. Однако, данную возможность можно реализовать на макросах
  84. Конструкции Linq.
  85. модуль Lazy стандартной библиотеки Ocaml.
  86. Реазилуется сторонними библиотеками, например cl-cont
  87. Только для байт-кода http://okmij.org/ftp/Computation/Continuations.html#caml-shift
  88. Легковесные процессы/Java. Вплоть до Java 1.1.
  89. Только в некоторых реализациях.
  90. Следует заметить что это не стандартные легкие процессы [5]
  91. Легковесные процессы/Python. Используя Stackless Python.
  92. Монадические потоки выполнения, реализованы в библиотеке Lwt
  93. Кортежи/C++. Реализуются в стандартной библиотеке (появились в TR1 (англоязычный раздел), до этого в boost).
  94. 1 2 Кортежи/.NET. С помощью типов System.Tuple<T,...> введёных в FCL 4.0.
  95. 1 2 Алгебраические типы данных/Ada и Delphi. Через механизм вариантных записей.
  96. 1 2 3 4 5 6 7 8 В динамических языках механизм алгебраических типов данных не имеет смысла.
  97. 1 2 3 4 5 Массива/Haskell. В языке не существует понятия "массив", вместо которого есть понятие "список".
  98. Динамические массивы/C. "Из коробки" данной возможности нет, однако похожий функционал можно реализовать, используя функцию realloc.
  99. Контроль границы массивов/С++. Для массивов контроля нет, однако в STL входит шаблон std::vector в который может быть встроен контроль границ (в перегрузку оператора индексации).
  100. 1 2 3 Контроль границ массивов/Perl, PHP и JavaScript. В языке нет массивов со статическими границами, присваивание элементу за текущими границами массива просто расширяет границы массива.
  101. Контроль границ массивов/Ocaml. Можно отключить на этапе компиляции с помощью ключа -unsafe
  102. Цикл foreach/Ada. Методы Iterate и Reverse_Iterate различных контейнеров, входящих в библиотеку Ada.Containers.
  103. Цикл foreach/C++. Алгоритм for_each из библиотеки STL.
  104. Цикл foreach/Erlang. В виде функции foreach/3 из модуля lists.
  105. Цикл foreach/JavaScript. С версии 1.6[6].
  106. Цикл foreach/Lisp. Макрос LOOP в составе стандартной библиотеки. Представляет собой "язык в языке" с большим количеством возможностей.
  107. List comprehensions/C#. "Query Comprehension" можно считать за List Comprehension только с большой натяжкой.
  108. 1 2 3 Целые числа произвольной длины/.NET. Посредством типа System.Numerics.BigInteger, включенного в FCL версии 4.0.
  109. Целые числа произвольной длины/Java. С помощью классов BigInteger и BigDecimal.
  110. Целые числа произвольной длины/Scala. С помощью классов BigInteger и BigDecimal.
  111. Целые числа произвольной длины/OCaml. В помощью модуля Num и Big_int.
  112. Пример: Тип (INTEGER 0 9) включает в себя все цифры от 0 до 9
  113. Целые числа произвольной длины/Perl. С помощью модуля Tie::Scalar.
  114. Похожий функционал реализуется макросами и средствами CLOS.
  115. Через множественное наследование от классов с методами-заготовками. См. [7]
  116. 1 2 3 4 Реализуется сторонними библиотеками
  117. Подмешивание реализации интерфейсов через ключевое слово implements. См. страницы 10-7 и 10-8 в Object Pascal Guide.
  118. Только совместное использование посредством виртуального наследования
  119. Для каждого члена класса - выбор дублирование (через переименование), или слияние (иначе, если не было переопределения)
  120. [8]
  121. http://www.digitalmars.com/d/2.0/function.html#pure-functions
  122. в форме указателей на функции
  123. указатели на методы
  124. 1 2 3 Появились в Delphi2009, как анонимные функции.
  125. Анонимные делегаты присутствуют в языке с версии 2.0. В C# 3.0 появились полноценные анонимные функции.
  126. Макрос LAMBDA
  127. Макросы/C. Посредством препроцессора C.
  128. Макросы/C++. Шаблоны C++ (изначально предназначенных для обобщенного программирования) возможно применять для метапрограммирования.
  129. Макросы/D. С++-подобные шаблоны.
  130. Макросы/Haskell. Template Haskell - препроцессор, встроенный в GHC.
  131. Штатный препроцессор camlp4
  132. 1 2 3 4 5 6 7 Неприменимо в языках с динамической типизацией.
  133. Generics/Haskell. Прямых аналогов шаблонов в языке нет, однако имеются не менее мощные средства обобщенного программирования.
  134. Generics/Delphi. Доступно начиная с Delphi 2009.
  135. Unicode в идентификаторах/C. Доступно в компиляторах gcc начиная с 4.2
  136. Unicode в идентификаторах/C++. Доступно в компиляторах от MS, начиная с MSVS++ 2005 и в gcc начиная с 4.2
  137. В большинстве современных реализаций
  138. Unicode в идентификаторах/Python. Доступно начиная с Python 3.0.
  139. Unicode в идентификаторах/Ruby. Доступно начиная с Ruby 1.9.
  140. Перегрузка функций/JavaScript. Можно сымитировать, используя проверку передаваемых параметров с помощью рефлексии.
  141. Обобщенные функции можно перегружать по типам или значениям нескольких параметров
  142. Только перегрузка операторов [9].
  143. 1 2 Перегрузка функций и сопоставление с образцом/Python. Реализовано в сторонней библиотеке PEAK-rules.
  144. макросы DEFVAR и DEFPARAMETER, а также декларация SPECIAL, создают динамические биндинги.
  145. 1 2 Именованные аргументы и параметры по умолчанию/C#. Доступно начиная с C# 4.0.
  146. Именованные параметры/JavaScript. Можно сымитировать, передав в качестве параметра функции JSON-объект: f ({param1: "value1", param2: "value2"}).
  147. Спецификатор "&key" в списке аргументов объявляемой функции объявляет именованный параметр.
  148. Именованные параметры/Smalltalk. Можно называть методы в стиле сделатьЧтоНибудьС:используя:и: - в таком случае двоеточия обозначают места, куда будут подставляться параметры при вызове метода, например сделатьЧтоНибудьС: парам1 используя: парам2 и: парам3. Названия подбирают таким образом, чтобы при вызове было понятно, для чего будут использоваться параметры.
  149. Именованные параметры/Delphi: Могут использоваться при вызове OLE: Word.Openfile(filename='1.doc')
  150. Значения параметров по умолчанию/Erlang. Можно сымитировать с помощью арности функции.
  151. "&key" и "&optional" параметры допускают значения по умолчанию
  152. Значения параметров по умолчанию/Perl. Можно элементарно сымитировать, см. [10].
  153. Локальные функции/С. Поддерживаются в компиляторе gcc как нестандартное расширение языка, см. [11].
  154. Локальные функции/С++. Поддерживаются в виде методов локальных классов
  155. Локальные функции/Java. Внутри метода можно определять безымянные (анонимные) локальные классы, которые фактически позволяют создавать экземпляры объектов, перекрывающие методы своего класса.
  156. Cпециальный оператор LABELS
  157. EQL спецификатор в обобщенных функциях можно рассматривать как аналог некоторого подмножества функциональности сопоставления с образцом
  158. 1 2 3 Посредством библиотеки Code Contracts из состава FCL 4.0.
  159. Контрактное программирование/Java. На основе аннотаций Java 5, используя библиотеку OVal и аспектный компилятор AspectJ.
  160. Контрактное программирование/Haskell. Посредством библиотеки QuickCheck.

[править] Терминология

[править] Парадигмы

[править] Императивный

Противоположность декларативному. Императивный язык должен описывать не столько саму задачу, сколько её решение. Несмотря на различие декларативных и императивных языков в конечном счёте скомпилированная программа представляет собой набор чётких и недвусмысленных инструкций, т.е. императивна.

[править] Объектно-ориентированный

Объектно-ориентированный язык позволяет использовать три парадигмы ООП: наследование, инкапсуляцию и полиморфизм.

[править] Рефлексивный

Наличие в языке мощных механизмов интроспекции, функции eval. Возможность программы на данном языке оперировать собственным кодом как данными.

[править] Функциональный

Позволяет записывать программу как композицию функций. В чистом функциональном языке нет переменных. Так как функции не имеют побочных эффектов, они могут выполняться в любом порядке.

[править] Обобщенное программирование

Обобщенное программирование позволяет записывать алгоритмы, принимающие данные любого типа.

[править] Логический

Использует логику предикатов для описания баз данных и процедур логического вывода и принятия решений

[править] Доказательный

Направлен на разработку алгоритмов и программ с доказательствами их правильности с использованием спецификаций программ.

[править] Декларативный

Противоположность императивному. Декларативный язык описывает не столько решение проблемы, сколько саму проблему, а решение уже должен определять компьютер. Следует заметить, что различие между императивными и декларативными языками условно, поскольку на любом языке можно писать фрагменты кода в декларативном стиле.

[править] Распределенный

Язык, содержащий специальные конструкции для поддержки распараллеливания программы на несколько компьютеров.

[править] Типизация

[править] Статическая типизация

(См. статическая типизация). Переменные и параметры методов/функций связываются с типами в момент объявления и не могут быть изменены позже.

[править] Динамическая типизация

(См. динамическая типизация). Переменные и параметры методов/функций связываются с типами в момент присваивания значения (или передачи параметра в метод/функцию), а не в момент объявления переменной или параметра. Одна и та же переменная в разные моменты может хранить значения разных типов.

[править] Явная типизация

Типы переменных и параметров указываются явно.

[править] Неявная типизация

Типы переменных и параметров не указываются явно. Неявная типизация может быть и статической, в таком случае типы переменных и параметров вычисляются компилятором.

[править] Явное приведение типов

Для использования переменной какого-то типа там, где предполагается использование переменной другого типа, нужно (возможно) явно выполнить преобразование типа.

[править] Неявное приведение типов без потери данных

Неявное приведение типов в таких ситуациях, где не происходит потери данных - например, использование целого числа там, где предполагалось использование числа с плавающей точкой.

[править] Неявное приведение типов с потерей данных

Неявное приведение типов в таких ситуациях, где может произойти потеря данных - например, использование числа с плавающей точкой там, где предполагалось использование целого числа.

[править] Неявное приведение типов в неоднозначных ситуациях

Например, использование строки там, где предполагалось число или наоборот. Классический пример: сложить число 1 со строкой "2" - результат может быть как число 3, так и строка "12". Другой пример - использование целого числа там, где ожидается логическое значение (boolean).

[править] Алиасы типов

Возможность определить видимый глобально (за пределами единицы компиляции) алиас типа, полностью эквивалентный исходному типу. Например, typedef в Си. Директива using в C# не подходит под этот критерий из-за локальной области действия.

[править] Вывод типов переменных из инициализатора

Возможность не указывать явно тип переменной, если для неё задан инициализатор. Если возможность действует для локальных переменных, но не действует для полей класса, все равно ставьте +. Характеристика не применима к языкам с динамической типизацией.

[править] Вывод типов переменных из использования

Возможность не указывать явно тип переменной, если её тип может быть выведен из дальнейшего использования. Если возможность действует для локальных переменных, но не действует для полей класса, все равно ставьте +. Характеристика не применима к языкам с динамической типизацией.

[править] Вывод типов-аргументов при вызове метода

Возможность не указывать явно типы-аргументы при вызове generic-метода, если они могут быть выведены из типов обычных аргументов.

[править] Вывод сигнатуры для локальных функций

Может ли сигнатура локальной функции быть выведена из использования. Неприменимо для языков с динамической типизацией. Ставьте -, если язык не поддерживает локальных функций.

[править] Параметрический полиморфизм

Наличие типобезопасного параметрического полиморфизма (aka generic types). Подразумевает возможность указывать constraints или type classes для типов-параметров.

[править] Параметрический полиморфизм с ковариантностью

Наличие ко- и контравариантных type parameters. В некоторых языках может быть лишь частичная поддержка (например, только в интерфейсах и делегатах). В таком случае, отмечайте +/-.

[править] Параметрический полиморфизм высших порядков

Возможность создавать type constructors высших порядков (как в Scala). См. Towards Equal Rights for Higher-kinded Types

[править] Информация о типах в runtime

Возможность узнать точный тип объекта в runtime.

[править] Информация о типах-параметрах в runtime

Возможность узнать в runtime информацию о типе, с которых инстанциирован generic-тип. Если язык не поддерживает generic-типы, то ставьте -. Если информация о типах стирается в runtime (используется erasure), то ставьте -.

[править] Компилятор/интерпретатор

[править] Open-source компилятор (интерпретатор)

Наличие полноценного open-source компилятора (для интерпретируемых языков — интерпретатора). Если существует open-source компилятор, но он поддерживает не все возможности языка, то ставьте +/- или -/+.

[править] Возможность компиляции

Возможность компиляции в нативный код или в byte-код с возможностью JIT-компиляции. Если язык компилируется в код на другом языке (например, C), который потом компилируется в нативный код, то тоже ставьте +.

[править] Bootstrapping компилятор

Наличие полноценного open-source bootstrapping компилятора (то есть, компилятора, написанного на том же языке, который он компилирует, и успешно компилирующего самого себя). Если существует open-source bootstrapping компилятор, но он поддерживает не все возможности языка, то ставьте +/- или -/+.

[править] Многопоточная компиляция

Возможность компилятора на многопроцессорных системах использовать несколько потоков для ускорения компиляции. Если язык не поддерживает компиляцию, то ставьте x (неприменимо).

[править] Интерпретатор командной строки

Возможность вводить инструкции языка строка за строкой с их немедленным выполнением. Может использоваться в качестве калькулятора.

[править] Условная компиляция

Возможность включать/выключать части кода в зависимости от значения символов условной компиляции (например, с помощью #if … #endif в C++)

[править] Управление памятью

[править] Объекты на стеке

Возможность создавать экземпляры объектов не в куче, а на стеке.

[править] Неуправляемые указатели

Наличие неуправляемых указателей, адресная арифметика, прямой доступ к памяти.

[править] Ручное управление памятью

Возможность явного выделения и освобождения памяти в куче (например, с помощью операторов new и delete в C++).

[править] Сборка мусора

Возможность использовать автоматический процесс сборки мусора (освобождения памяти в куче, занятой неиспользуемыми объектами).

[править] Управление потоком вычислений

[править] Инструкция goto

Поддержка инструкции goto (безусловный переход на метку). Отсутствует в языках структурного программирования.

[править] Инструкция break без метки

Поддержка инструкции break без метки (безусловный выход из ближайшего цикла), и соответствующей инструкции continue. Наличие в языке инструкции break, относящегося к switch или другой конструкции, не влияет на это поле.

[править] Инструкция break с меткой

Поддержка инструкции break с меткой (безусловный выход из цикла, помеченного меткой), и соответствующей инструкции continue. Наличие в языке инструкции break, относящегося к switch или другой конструкции, не влияет на это поле.

[править] Поддержка try/catch

Поддержка обработки исключений с помощью try/catch или эквивалентной конструкции.

[править] Блок finally

Поддержка блока finally при обработке исключений или эквивалентной конструкции.

[править] Блок else (исключения)

Поддержка блока else при обработке исключений (действия, выполняющиеся при завершении блока try без исключения).

[править] Перезапуски

Исключения, не раскручивающие стек вызовов. Возможность из места перехвата исключения вернуться в место установки перезапуска.

[править] Легковесные процессы

Эмуляция многопоточности рантаймом самого языка. В пределах одного (или нескольких) потока ОС выполняется множество потоков исходного кода

[править] Типы и структуры данных

[править] Многомерные массивы

Наличие встроенных в язык многомерных массивов. Если язык поддерживает только массивы массивов, ставьте +/-

[править] Динамические массивы

Наличие встроенных в язык динамических массивов (способных изменять свой размер во время выполнения программы).

[править] Ассоциативные массивы

Наличие встроенных в язык ассоциативных массивов или хэш-таблиц.

[править] Цикл foreach

Наличие возможности перебрать все элементы коллекции с помощью цикла foreach. Если в языке есть эквивалентная или более сильная возможность (наподобие list comprehensions), ставьте +.

[править] List comprehensions

Наличие List comprehensions (или аналога).

[править] Кортежи

Возможность вернуть из функции/метода кортеж (tuple) — неименованный тип данных, содержащий несколько безымянных полей произвольного типа.

[править] Целые числа произвольной длины

Поддержка целых чисел неограниченной разрядности. Должна быть возможность записать сколь угодно большое целое число с помощью литерала.

[править] Целые числа с контролем границ

Возможность определить тип, значениями которого могут быть целые числа только определенного интервала, например [-5..27], при этом присвоение переменной такого типа значения, выходящего за указанные рамки, должно вызывать ошибку.

[править] Объектно-ориентированные возможности

[править] Интерфейсы

Семантическая и синтаксическая конструкция в коде программы, используемая для специфицирования услуг, предоставляемых классом. См. Интерфейс в ООП.

[править] Множественное наследование

Возможность наследовать класс сразу от нескольких классов (не интерфейсов).

[править] Мультиметоды

Динамическая (run time) диспетчеризация функции в зависимости от типов нескольких аргументов.
В языках с "message passing" ООП похожий функционал реализуется паттерном "Visitor".

[править] Переименование членов при наследовании

Возможность в наследнике изменить имя поля/метода предка.

[править] Решение конфликта имен при множественном наследовании

При множественном наследовании - решение для случая ромбовидного наследования (B потомок A, C потомок A, D потомок B и C). Решение может приниматься как для всего класса, так и для каждого поля/метода в отдельности.

[править] Функциональные возможности

[править] First class functions

Функции в данном языке являются объектами первого класса.

[править] Лексические замыкания

Возможность использовать локальную или лямбда-функцию (анонимный делегат) за пределами функции-контейнера с автоматическим сохранением контекста (локальных переменных) функции-контейнера

[править] Разное

[править] Макросы

Наличие в языке макро-системы, обрабатывающей код программы до времени её компиляции и/или выполнения. Например, макросы Лиспа, препроцессор Си или шаблоны С++.

[править] Шаблоны/Generics

Наличие в данном статически типизированном языке инструмента для обобщенного программирования, наподобие templates в C++ или generics в C#.

[править] Поддержка Unicode в идентификаторах

Возможность включения Unicode-символов (например, букв национальных алфавитов) в идентификаторы.

[править] Перегрузка функций

(См. перегрузка функций). Возможность перегрузки функций/методов по количеству и типам параметров.

[править] Динамические переменные

Возможность создавать переменные, имеющие.динамическую область видимости(англ.).

[править] Именованные параметры

Возможность при вызове функции/метода указывать имена параметров и менять их местами.

[править] Значения параметров по умолчанию

Возможность при вызове функции/метода опускать некоторые параметры, чтобы при этом подставлялось значение по умолчанию, указанное при определении функции.

[править] Локальные функции

Возможность определять локальную функцию внутри другой функции/метода. Подразумевается возможность использовать внутри локальной функции локальные переменные из внешнего блока.

[править] Сопоставление с образцом

Наличие сопоставления с образцом.

[править] Контрактное программирование

Возможность задавать пред- и пост-условия для методов и инварианты для классов. Подробнее см. Design by contract(англ.).

[править] Ссылки